#该函数模块包含贪婪策略与贪婪参数的动态调整过程

import random
import numpy as np
# import cupy as np
import pandas as pd
# import modin.pandas as pd
from random import choice

flight_state = pd.read_pickle(r'C:\Users\HP\Desktop\adaRLAMRP\case_pkl\case8.8.pkl')#读取航班状态信息
aircraft_action =pd.read_pickle(r'C:\Users\HP\Desktop\adaRLAMRP\case_pkl\飞机8.8.pkl')#读取航班状态信息#读取飞机行为可选信息
base_inf = pd.read_pickle(r'C:\Users\HP\Desktop\adaRLAMRP\case_pkl\基地8.pkl')#读取航班状态信息#读取基地信息，用于基地容量约束

# flight_state = pd.read_csv(r'C:\Users\HP\Desktop\adaRLAMRP\case\case8.8.csv',encoding='gbk')#读取航班状态信息
# aircraft_action = pd.read_csv(r'C:\Users\HP\Desktop\adaRLAMRP\case\飞机8.8.csv')#读取飞机行为可选信息
# base_inf = pd.read_csv(r'C:\Users\HP\Desktop\adaRLAMRP\case\基地8.csv',encoding='gbk')#读取基地信息，用于基地容

def TC_epsilon_greedy_policy(state, list, epsilon,qfun):
    #STATE代表航班号、list代表TC状态合集、epsilon代表筛选概率、qfun代表q价值数
    state = state
    list = list
    epsilon = epsilon
    qfun = qfun
    # 概率部分
    if np.random.uniform() < 1 - epsilon: #轮盘赌的概率选择函数
        # 最优动作
        qfun = qfun[:,list] #筛选TC中存在的航班信息集合
        action1 = qfun[state, :].argmax()  # 用于查找Q表中价值最大的位置对应的飞机号，即为所应该选择的动作
        action = list[action1]
        return action
    else:
        action = choice(list) #随机选取TC中的飞机号作为动作
        return action


def NC_epsilon_greedy_policy(state, list, NIU,MTN,aircraft_maintain,epsilon,qfun,aircraft_list):
    #STATE代表航班号、list代表TC状态合集、epsilon代表筛选概率、qfun代表q价值数
    state = state
    list = list
    NIU = NIU
    MTN = MTN
    aircraft_maintain = aircraft_maintain
    epsilon = epsilon
    qfun = qfun
    aircraft_list = aircraft_list
    # 概率部分
    if np.random.uniform() < 1 - epsilon: #轮盘赌的概率选择函数
        # 最优动作
        qfun = qfun[:,list] #筛选NC中存在的航班信息集合
        action1 = qfun[state, :].argmax()  # 用于查找Q表中价值最大的位置对应的飞机号，即为所应该选择的动作
        action = list[action1]
        return action
    else:
        if len(NIU)==0:
           action = choice(list) #随机选取NC中的飞机号作为动作
           return action
        if not len(NIU)==0:#查找未用飞机中满足所属机场的第一个可用飞机
            check_time = flight_state.at[state, 'dep_time']
            if not len(MTN) == 0:  # 当MTN不为空时
                for i in MTN:
                    # 查找i对应的维修航段
                    M_S = aircraft_maintain[i]  # 找到此时飞机i所在的维修航段及其状况
                    M_start = flight_state.at[M_S, 'arr_time']
                    M_air = flight_state.at[M_S, 'arr_air']
                    M_end = M_start + 480  # 该飞机结束维修的时间
                    if ((M_end < check_time) and (M_air==flight_state.at[state, 'dep_air'])):
                        MTN.remove(i)
                        NIU.append(i)
                        aircraft_maintain[i] = 0  # 将此维修航段去除，该飞机不维修了
            NIU1 = NIU
            for i in NIU:
                if not len(aircraft_list[i]) == 0:
                    if not (flight_state.at[aircraft_list[i][-1], 'arr_air'] == flight_state.at[state, 'dep_air']):
                        NIU1.remove(i)
            aircraft_available = aircraft_action[aircraft_action.index.isin(NIU1)]  # 将NIU中飞机的信息筛选出来
            s_action = aircraft_available
            s_action = min(s_action.index)  # 此时筛选得出可用飞机的索引号，即课代表选择的飞机号
            list.append(s_action)
            action = choice(list)
            return action

def epsilon_decrease(epilon,Ge_list,episode,reward_sample):
    epilon = epilon
    Ge_list = Ge_list
    episode = episode
    Ge_current = Ge_list[episode]
    Ge_pre = Ge_list[episode-1]
    reward_sample = reward_sample
    m1 = 0
    for i in  Ge_list:
        if i <Ge_current:
            m1 += 1
    #设置贪心策略的衰减规则--------------后续应该要修改，先写一个在这里
    diff =  Ge_current-Ge_pre
    # k = 0.99998
    # k2 = 0.99998
    # k3 = 0.9995
    # epilon1 = epilon *(k3**episode)
    # return epilon1

    if  episode<120:
     if diff>0:
        epilon1 = epilon
     if diff <= 0:
       # epilon1 = epilon * math.pow(k2,episode)
       u = list(filter(lambda x: x == 10, reward_sample))
       epilon1 = epilon * (0.9 / (0.9 + (1 / len(u))))
       # epilon1 = epilon *  (k**episode)
     return epilon1
    if episode>=120:
        # if diff < 0:
        #     epilon1 = epilon
        # if diff >= 0:
        #  if Ge_current == max(Ge_list):
        #     epilon1 = epilon * math.pow(k3, episode)
        #  else:
        #    decay = 100
        #    epilon1 = 0+(0.5-0)*math.exp(-episode/decay)

      # epilon1 = epilon *(k3**episode)
      u = list(filter(lambda x: x == 10, reward_sample))
      epilon1 = epilon * (0.9 / (0.9 + (1 / len(u)))) ** (episode -120)
      return epilon1
